#include "AutoSnifferCtrl.h"
#include "SnifferManager.h"
#include "eutranCtrl.h"
#include "EutranConfigData.h"

AutoSnfStratety::AutoSnfStratety(std::string name):
autoSnfCtrl_(NULL),
name_(name)
{
}

bool AutoSnfStratety::setSnfCtrl(AutoSnifferCtrl* ptr)
{
    if( ptr==NULL )
    {
        EMLogError("ptr is NULL");
        return false;
    }
    autoSnfCtrl_ = ptr;
    return true;
}

std::string AutoSnfStratety::getName()
{
    return name_;
}


AutoSnfByTime::AutoSnfByTime(): 
AutoSnfStratety("AUTO SNF BY TIME"),
day_(0),
hour_(0),
min_(0),
autoSnfTimer_(3600),
autoSnfHandler_(this, &AutoSnfByTime::startSniffer)
{
}

AutoSnfByTime::~AutoSnfByTime()
{
}

bool AutoSnfByTime::setStartTime(uint16_t day, uint8_t hour, uint8_t min)
{
    if( hour>23 || min>59)
    {
        EMLogError("Invalid hour: %d", static_cast<uint32_t>(hour));
        return false;
    }

    day_ = day;
    hour_ = hour;
    min_ = min;
    time_t currentTime = time(NULL);
    struct tm targetTm = *localtime(&currentTime);

    targetTm.tm_hour = hour;
    targetTm.tm_min = min;
    targetTm.tm_sec = 0;
    time_t targetTime = mktime(&targetTm);

    time_t delta = 0;
    if( currentTime < targetTime )
    {
        delta = targetTime - currentTime;
    }
    else
    {
        delta = 24*60*60 - (currentTime - targetTime);
    } 

    delta += day_*24*60*60;

    autoSnfTimer_ = delta;
    EMLogInfo("Set auto sniffer at %d:%d, sec=%d", static_cast<uint32_t>(hour), static_cast<uint32_t>(min), autoSnfTimer_);
    return true;
}

bool AutoSnfByTime::start(AutoSnifferCtrl* ctrl)
{
    autoSnfCtrl_ = ctrl;
    if( autoSnfCtrl_==NULL )
    {
        EMLogError("autoSnfCtrl_ is NULL");
        return false;
    }
    
    return EutranTimerPtr->queue(autoSnfTimer_, &autoSnfHandler_);
}

bool AutoSnfByTime::stop()
{
    return EutranTimerPtr->dequeue(&autoSnfHandler_);
}

void AutoSnfByTime::startSniffer()
{
    autoSnfCtrl_->startSniffer();

    autoSnfTimer_ = day_*24*60*60;
    EutranTimerPtr->queue(autoSnfTimer_, &autoSnfHandler_);
}

AutoSnifferCtrl::AutoSnifferCtrl(BbuCtrl* ptr):
strategy_(NULL),
bbuPtr_(ptr),
isActive_(false),
retrySnfTimer_(180),
retrySnfHandler_(this, &AutoSnifferCtrl::restartSniffer)
{
}

bool AutoSnifferCtrl::start(AutoSnfStratety* strategy)
{
    if( bbuPtr_==NULL )
    {
        EMLogError("NULL pointer");
        return false;
    }

    if( isActive_ )
    {
        EMLogError("BBU[%d]: AutoSnifferCtrl has been active", bbuPtr_->getInstance().getSlotId());
        return false;
    }

    if( strategy==NULL )
    {
        EMLogError("BBU[%d]: NULL pointer", bbuPtr_->getInstance().getSlotId());
        return false;
    }
    if( strategy_!=NULL )
    {
        EMLogError("BBU[%d]: strategy_ is not NULL, memory leak?", bbuPtr_->getInstance().getSlotId());
        delete strategy_;
        strategy_ = NULL;
    }
    
    strategy_ = strategy;
    isActive_ = true;

    if( !strategy_->start(this) )
    {
        EMLogError("BBU[%d]: Fail to start strategy", bbuPtr_->getInstance().getSlotId());
        delete strategy_;
        strategy_ = NULL;
        isActive_ = false;
        return false;
    }

    EMLogInfo("BBU[%d]: Start auto sniffer strategy: %s", bbuPtr_->getInstance().getSlotId(), strategy_->getName().c_str());
    return true;
}

bool AutoSnifferCtrl::isActive()
{
    return isActive_;
}

void AutoSnifferCtrl::stop()
{
    EutranTimerPtr->dequeue(&retrySnfHandler_);
    isActive_ = false;
    arfcnRange_.clear();
    
    if( strategy_!=NULL )
    {
        strategy_->stop();
        delete strategy_;
        strategy_ = NULL;
    }
}

void AutoSnifferCtrl::startSniffer()
{
    EMLogInfo("BBU[%d]: auto start sniffer of RSSI", bbuPtr_->getInstance().getSlotId());

    EutranTimerPtr->dequeue(&retrySnfHandler_);
    if( !SnifferMgrPtr->startSniffer(AUTO_SNF_TRIGGER, bbuPtr_->getInstance().getSlotId(), arfcnRange_) )
    {
        EMLogError("BBU[%d]: Fail to start auto sniffer, retry after %d sec", bbuPtr_->getInstance().getSlotId(), retrySnfTimer_);
        EutranTimerPtr->queue(retrySnfTimer_, &retrySnfHandler_);
    }
}

void AutoSnifferCtrl::indicateBbuDeactive()
{
    if( isActive_ )
    {
        EMLogInfo("BBU[%d]: BBU is deactive, retry after 2 min", bbuPtr_->getInstance().getSlotId());

        EutranTimerPtr->queue(retrySnfTimer_, &retrySnfHandler_);
    }
}

void AutoSnifferCtrl::restartSniffer()
{
    EMLogInfo("BBU[%d]: restartSniffer", bbuPtr_->getInstance().getSlotId());

    if( !SnifferMgrPtr->startSniffer(AUTO_SNF_TRIGGER, bbuPtr_->getInstance().getSlotId(), arfcnRange_) )
    {
        EMLogInfo("BBU[%d]: Fail to start auto sniffer, retry after %d sec", bbuPtr_->getInstance().getSlotId(), retrySnfTimer_);
        EutranTimerPtr->queue(retrySnfTimer_, &retrySnfHandler_);
    }
}

